package Server;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;

public class ServidorP2P implements Runnable{
	private Socket connection;
	private String TimeStamp;
	private int ID;
	private String noConectado;
	
	public static void main(String[] args) {
		int port = 19888;
		int count = 0;
		try{
		ServerSocket socket1 = new ServerSocket(port);
		while (true) {
		     Socket connection = socket1.accept();
		     Runnable runnable = new ServidorP2P(connection, ++count);
		     Thread thread = new Thread(runnable);
		     thread.start();
			}
		}
		    catch (Exception e) {}
	}
	
	public ServidorP2P(Socket s, int i) {
		  this.connection = s;
		  this.ID = i;
		}
	
	@Override
	public void run() {
		try {
			BufferedInputStream is;
			is = new BufferedInputStream(connection.getInputStream());
		
		    InputStreamReader isr = new InputStreamReader(is);
		    BufferedOutputStream os = new BufferedOutputStream(connection.getOutputStream());
	        OutputStreamWriter osw = new OutputStreamWriter(os, "US-ASCII");
	        //System.out.println(isr.read());
		    int comando = isr.read();
		    StringBuffer sb = new StringBuffer();
		    switch(comando){
		    	case GlobaisServidor.CRIAR_ARQUIVO:
		    		while((comando = isr.read()) != (int)'/'){
		    			sb.append((char) comando);
		    		}
		    		String nomeArquivo = sb.toString();
		    		System.out.println("Nome do arquivo criado: "+ nomeArquivo);
		    		sb.delete(0, sb.length());
		    		while((comando = isr.read()) != (int)'/'){
		    			sb.append((char) comando);
		    		}
		    		System.out.println("Codigo do no de origem: " + sb.toString());
		    		String nomeNo = sb.toString();
		    		sb.delete(0, sb.length());
		    		ArrayList<String> listaServer = new ArrayList<String>();
		    		listaServer.add(nomeNo);
		    		GlobaisServidor.tabelaArquivos.add(new InfoArquivo(nomeArquivo, listaServer));
		    		break;
		    	case GlobaisServidor.LER_ARQUIVO:
		    		while((comando = isr.read()) != (int)'/'){
		    			sb.append((char) comando);
		    		}
		    		nomeArquivo = sb.toString();
		    		System.out.println("Nome do arquivo lido: "+ nomeArquivo);
		    		sb.delete(0, sb.length());
		    		while((comando = isr.read()) != (int)'/'){
		    			sb.append((char) comando);
		    		}
		    		nomeNo = sb.toString();
		    		sb.delete(0, sb.length());
		    		GlobaisServidor.addClienteVector(nomeArquivo, nomeNo);
		    		String returnCode = "";
		    		int indice = GlobaisServidor.buscaArquivoVector(nomeArquivo);
		    		InfoArquivo infoArquivo = GlobaisServidor.tabelaArquivos.get(indice);
		    		for(int i = 0; i<infoArquivo.getNosServidores().size();i++){
		    			returnCode += infoArquivo.getNosServidores().get(i) + "/";
		    		}
		    		returnCode +="\0";
		    		osw.write(returnCode);
		            osw.flush();
		            
		      		break;
		      	case GlobaisServidor.ATUALIZAR_ARQUIVO:
		      		while((comando = isr.read()) != (int)'/'){
		    			sb.append((char) comando);
		    		}
		    		nomeArquivo = sb.toString();
		    		sb.delete(0, sb.length());
		    		while((comando = isr.read()) != (int)'/'){
		    			sb.append((char) comando);
		    		}
		    		nomeNo = "node"+comando;
		    		sb.delete(0, sb.length());
		    		indice = GlobaisServidor.addClienteVector(nomeArquivo, nomeNo);
		    		GlobaisServidor.tabelaArquivos.get(indice).setNoAtualizador(comando);
		    		//ENVIAR INFO NO SENDO ATT - AXO Q NAO VAMOS FAZER ATUALIZACAO
		      		break;
		      	case GlobaisServidor.REMOVER_ARQUIVO:
		      		while((comando = isr.read()) != (int)'/'){
		    			sb.append((char) comando);
		    		}
		    		nomeArquivo = sb.toString();
		    		System.out.println("Nome do arquivo removido: "+ nomeArquivo);
		    		sb.delete(0, sb.length());
		    		while((comando = isr.read()) != (int)'/'){
		    			sb.append((char) comando);
		    		}
		    		nomeNo = sb.toString();
		    		sb.delete(0, sb.length());
		    		Boolean resposta = GlobaisServidor.removerServidorVector(nomeArquivo,nomeNo);
		    		osw.write(resposta.toString()+"\0");
		            osw.flush();
		      		break;
		      	case GlobaisServidor.MOVER_ARQUIVO:
		      		while((comando = isr.read()) != (int)'/'){
		    			sb.append((char) comando);
		    		}
		    		nomeArquivo = sb.toString();
		    		sb.delete(0, sb.length());
		    		while((comando = isr.read()) != (int)'/'){
		    			sb.append((char) comando);
		    		}
		    		String nomeNoOrigem = sb.toString();
		    		sb.delete(0, sb.length());
		    		while((comando = isr.read()) != (int)'/'){
		    			sb.append((char) comando);
		    		}
		    		String nomeNoDestino = sb.toString();
		    		System.out.println("Nome do arquivo movido: "+ nomeArquivo);
		    		System.out.println("Origem: "+nomeNoOrigem+" Destino: "+nomeNoDestino);
		    		sb.delete(0, sb.length());
		    		resposta = GlobaisServidor.novoServidorVector(nomeArquivo,nomeNoOrigem, nomeNoDestino);
		    		moverArquivo(nomeArquivo, nomeNoOrigem, nomeNoDestino);
		    		osw.write(resposta.toString()+"\0");
		            osw.flush();
		      		break;
		      	case GlobaisServidor.LIBERAR_ARQUIVO: //SEM UPDATE N PRECISA DISSO
		      		break;
		      	default:
		      		System.out.println("Comando desconhecido enviado ao servidor: "+ comando);
		      		break;
		    }
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
		      try {
		          connection.close();
		       }
		        catch (IOException e){}
		      }
	}
	
	private void moverArquivo(String nomeArquivo,String nomeNoOrigem,String nomeNoDestino){
		int port = 19887;
		StringBuffer instr = new StringBuffer();
		String TimeStamp;
		
		int i;
		try {
			 /** Obtain an address object of the server */
			 InetAddress address = InetAddress.getByName(nomeNoDestino);
			 /** Establish a socket connetion */
			 Socket connection = new Socket(address, port);
			 /** Instantiate a BufferedOutputStream object */
			 BufferedOutputStream bos = new BufferedOutputStream(connection.
			          getOutputStream());

			 /** Instantiate an OutputStreamWriter object with the optional character
			 * encoding.
			 */
			 OutputStreamWriter osw = new OutputStreamWriter(bos, "US-ASCII");
			 String process = (char)GlobaisServidor.MOVER_ARQUIVO+ nomeArquivo+ "/" 
					 + nomeNoOrigem + "/";
			 System.out.println("Processo de movimentacao: " + process);
			 /** Write across the socket connection and flush the buffer */
			 osw.write(process);
			 osw.flush();
		}
		catch (IOException f) {
			System.out.println("IOException: " + f);
		}
		catch (Exception g) {
		    System.out.println("Exception: " + g);
		}
	  
	}

}
